﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bluyel.Core
{
    /// <summary>
    /// Manager of all types.
    /// Just save types, no creation here.
    /// use the TypeBuilder to create types,
    /// Use the TypeFinder to looking for a type.
    /// </summary>
    public class TypeMgrBase
    {
        /// <summary>
        /// the type bool, its in the list.
        /// also here because used very often, so can it be accessed more quickly.
        /// </summary>
        private ITypeBasic _typeBool;

        /// <summary>
        /// the type string, its in the list.
        /// also here because used very often, so can it be accessed more quickly.
        /// </summary>
        private ITypeBasic _typeString;

        /// <summary>
        /// its in the list
        /// also here because used very often, so can it be accessed more quickly.
        /// </summary>
        private ITypeBasic _typeInt;

        private ITypeBasic _typeLong;

        /// <summary>
        /// the type double, its in the list.
        /// also here because used very often, so can it be accessed more quickly.
        /// </summary>
        private ITypeBasic _typeDouble;


        /// <summary>
        /// the type void, its in the list.
        /// also here because used very often, so can it be accessed more quickly.
        /// </summary>
        private ITypeVoid _typeVoid;

        /// <summary>
        /// The type data named structure.
        /// TODO: add typeClass?
        /// </summary>
        private ITypeStruct _typeStruct;

        // list of Base quantities 
        // TODO: faire un tableau!

        // list of General derived quantities
        // TODO:

        // Manager of multiples/prefix of the Length physQty.
        private PhyLengthPrefixMgr _phyLengthMultiples = new PhyLengthPrefixMgr();

        /**
         * Just for optimisation, the type is also stored in the list.
         */
        private TypePhyLength _typePhyLength;

        // TODO: type container, list of ITypeContainer

        /// <summary>
        /// list of basic types (string, int, double,...).
        /// </summary>
        private ListTypeGen<ITypeBasic> _listTypeBasic = new ListTypeGen<ITypeBasic>();

        private ListTypeGen<ITypeEnum> _listTypeEnum = new ListTypeGen<ITypeEnum>();

        private ListTypeGen<ITypePhy> _listTypePhy = new ListTypeGen<ITypePhy>();

 

        /// <summary>
        /// List of list of types.
        /// </summary>
        private List<ListType> _listListType = new List<ListType>();

        //=====================================================================
        #region Constructor.

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="factory"></param>
        public TypeMgrBase() //CoreSystem coreSystem)
        {
            //_coreSystem = coreSystem;
        }
        #endregion

        //=====================================================================
        #region Properties.

        //---------------------------------------------------------------------
        public ITypeBasic TypeInt
        {
            get { return _typeInt; }
        }
        //---------------------------------------------------------------------
        public ITypeBasic TypeLong
        {
            get { return _typeLong; }
        }
        //---------------------------------------------------------------------
        public ITypeBasic TypeDouble
        {
            get { return _typeDouble; }
        }
        //---------------------------------------------------------------------
        public ITypeBasic TypeString
        {
            get { return _typeString; }
        }
        //---------------------------------------------------------------------
        public ITypeBasic TypeBool
        {
            get { return _typeBool; }
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Get the Structure type.
        /// </summary>
        /// <returns></returns>
        public ITypeStruct TypeStruct
        {
            get { return _typeStruct; }
        }

        //---------------------------------------------------------------------
        public ITypeVoid TypeVoid
        {
            get { return _typeVoid; }
        }

        //---------------------------------------------------------------------        
        public TypePhyLength TypePhyLength
        {
            get { return _typePhyLength; }
        }

        //---------------------------------------------------------------------        
        /// <summary>
        /// Return all type basic.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ITypeBasic> ListTypeBasic
        {
            get { return _listTypeBasic.ListType; }
        }

        //---------------------------------------------------------------------        
        /// <summary>
        /// Return all type LOV.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ITypeEnum> ListTypeEnum
        {
            get { return _listTypeEnum.ListType; }
        }
        //---------------------------------------------------------------------        
        /// <summary>
        /// Return the list of ListType.
        /// </summary>
        public IEnumerable<ListType> ListListType
        { get { return _listListType; } }

        #endregion

        //=====================================================================
        #region Public Get/Set methods.

        //---------------------------------------------------------------------
        /**
         * Get the value coefficient of the prefix.
         * @param prefixSrc
         * @param prefixTgt
         * @return 
         */
        public double GetValCoeff(TypePhyLengthPrefix prefixSrc, TypePhyLengthPrefix prefixTgt)
        {
            return _phyLengthMultiples.GetCoeffByPrefix(prefixSrc, prefixTgt);
        }
        #endregion

        //=====================================================================
        #region Publics edit basic type methods.

        //---------------------------------------------------------------------
        public bool AddTypeBasic(ITypeBasic type)
        {
            if (type == null)
                return false;

            // check if not already present, (obj, Id, Name)
            //TODO:

            _listTypeBasic.Add(type);
            return true;
        }

        //---------------------------------------------------------------------
        public bool AddTypeInt(ITypeBasic type)
        {
            // the type already exists
            if (_typeInt != null)
                return false;
            // check the Id of the type int
            // TODO:

            if (!AddTypeBasic(type))
                return false;

            _typeInt = type;
            return true;
        }

        //---------------------------------------------------------------------
        public bool AddTypeLong(ITypeBasic type)
        {
            // the type already exists
            if (_typeLong != null)
                return false;
            // check the Id of the type 
            // TODO:

            if (!AddTypeBasic(type))
                return false;

            _typeLong = type;
            return true;
        }

        //---------------------------------------------------------------------
        public bool AddTypeDouble(ITypeBasic type)
        {
            // the type already exists
            if (_typeDouble != null)
                return false;
            // check the Id of the type Double
            // TODO:

            if (!AddTypeBasic(type))
                return false;

            _typeDouble = type;
            return true;
        }
        //---------------------------------------------------------------------
        public bool AddTypeString(ITypeBasic type)
        {
            // the type already exists
            if (_typeString != null)
                return false;
            // check the Id of the type String
            // TODO:

            if (!AddTypeBasic(type))
                return false;

            _typeString = type;
            return true;
        }
        //---------------------------------------------------------------------
        public bool AddTypeBool(ITypeBasic type)
        {
            // the type already exists
            if (_typeBool != null)
                return false;
            // check the Id of the type Bool
            // TODO: in all list of type!

            if (!AddTypeBasic(type))
                return false;

            _typeBool = type;
            return true;
        }

        #endregion

        //=====================================================================
        #region Publics edit specifics type methods.

        //---------------------------------------------------------------------
        public bool AddTypeVoid(ITypeVoid type)
        {
            // the type already exists
            if (_typeVoid != null)
                return false;

            _typeVoid = type;
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add the type DataNamed Structure (is unique).
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public bool AddTypeStruct(ITypeStruct type)
        {
            // the type already exists
            if (_typeStruct != null)
                return false;

            _typeStruct = type;
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a new typeLOV.
        /// 
        /// The name must be not used by another type (check in the TypeBuilder).
        /// </summary>
        /// <param name="typeEnum"></param>
        /// <returns></returns>
        public bool AddTypeEnum(ITypeEnum typeEnum)
        {
            if (typeEnum == null)
                return false;

            _listTypeEnum.Add(typeEnum);
            return true;
        }

        //---------------------------------------------------------------------
        public  bool RemoveTypeEnum(ITypeEnum typeEnum)
        {
            return _listTypeEnum.Remove(typeEnum);
        }

        //---------------------------------------------------------------------
        public bool AddTypePhyLength(TypePhyLength physQty)
        {
            if (physQty == null)
                return false;

            // check if not already added
            if (_typePhyLength != null)
                return false;

            // save it 
            _typePhyLength = physQty;

            _listTypePhy.Add(physQty);
            return true;
        }

        #endregion

        //=====================================================================
        #region Publics Edit ListType methods.

        //---------------------------------------------------------------------
        public bool AddListType(ListType listType)
        {
            if (listType == null)
                return false;

            // check if the name is already used by a list
            // TODO:

            _listListType.Add(listType);
            return true;
        }

        // remove a list type
        // TODO:

        #endregion

        //=====================================================================
        #region Privates methods.
        #endregion
    }
}
